﻿using System;
using System.Collections.Generic;
using System.Data;
using CRMBiz;

namespace CRMWeb.Pages
{
    public partial class TestCalculator : CRMWeb.Utilities.BasePage
    {
        protected void Page_Load(object sender, EventArgs e)
        {
        }

        //No Interest by term
        protected void Button1_Click(object sender, EventArgs e)
        {
            //decimal loanAmount = 250;
            //int term = 8;
            //int daysBetweenRepayments = 7;
            //DateTime settlementDate = new DateTime(2013, 7, 3);
            //DateTime firstPaymentDate = new DateTime(2013, 7, 10);

            Label2.Visible = true;
            txtTerm.Visible = true;
            Label9.Visible = false;
            txtRepayment.Visible = false;

            decimal loanAmount = Convert.ToDecimal(txtLoanAmount.Text);
            int term = Convert.ToInt16(txtTerm.Text);
            int daysBetweenRepayments = Convert.ToInt16(txtDaysBetween.Text);
            DateTime settlementDate = Convert.ToDateTime(txtFirstDate.Text);
            DateTime firstPaymentDate = Convert.ToDateTime(txtFirstPaymentDate.Text);

            NoInterestPaymentSchedule(term, loanAmount, daysBetweenRepayments, settlementDate, firstPaymentDate);
        }

        //No interest by repayment
        protected void Button2_Click(object sender, EventArgs e)
        {
            Label2.Visible = false;
            txtTerm.Visible = false;
            Label9.Visible = true;
            txtRepayment.Visible = true;

            decimal loanAmount = Convert.ToDecimal(txtLoanAmount.Text);// 5000;
            decimal repaymentAmount = Convert.ToDecimal(txtRepayment.Text);
            int daysBetweenRepayments = Convert.ToInt16(txtDaysBetween.Text);
            DateTime settlementDate = Convert.ToDateTime(txtFirstDate.Text);
            // new DateTime(2013, 6, 29);
            //  DateTime a = Convert.ToDateTime(txtFirstDate.txt);
            //  DateTime firstPaymentDate = new DateTime(2013, 7, 7);
            DateTime firstPaymentDate = Convert.ToDateTime(txtFirstPaymentDate.Text);
            decimal annumInterestRate = Convert.ToDecimal(txtInterestRatePA.Text);

            NoInterestPaymentScheduleByRepayment(repaymentAmount, loanAmount, daysBetweenRepayments, settlementDate, firstPaymentDate, annumInterestRate);
        }

        //simple interest by repayment
        protected void Button3_Click(object sender, EventArgs e)
        {
            Label2.Visible = false;
            txtTerm.Visible = false;
            Label9.Visible = true;
            txtRepayment.Visible = true;

            decimal loanAmount = Convert.ToDecimal(txtLoanAmount.Text);// 5000;
            decimal repaymentAmount = Convert.ToDecimal(txtRepayment.Text);
            int daysBetweenRepayments = Convert.ToInt16(txtDaysBetween.Text);
            DateTime settlementDate = Convert.ToDateTime(txtFirstDate.Text);
            // new DateTime(2013, 6, 29);
            //  DateTime a = Convert.ToDateTime(txtFirstDate.txt);
            //  DateTime firstPaymentDate = new DateTime(2013, 7, 7);
            DateTime firstPaymentDate = Convert.ToDateTime(txtFirstPaymentDate.Text);
            decimal annumInterestRate = Convert.ToDecimal(txtInterestRatePA.Text);

            SimpleInterestPaymentScheduleByRepayment(repaymentAmount, loanAmount, daysBetweenRepayments, settlementDate, firstPaymentDate, annumInterestRate);
        }

        //simple interest by term
        protected void Button4_Click(object sender, EventArgs e)
        {

            Label2.Visible = true;
            txtTerm.Visible = true;
            Label9.Visible = false;
            txtRepayment.Visible = false;

            decimal loanAmount = Convert.ToDecimal(txtLoanAmount.Text);
            int term = Convert.ToInt16(txtTerm.Text);
            int daysBetweenRepayments = Convert.ToInt16(txtDaysBetween.Text);
            DateTime settlementDate = Convert.ToDateTime(txtFirstDate.Text);
            DateTime firstPaymentDate = Convert.ToDateTime(txtFirstPaymentDate.Text);
            decimal annumInterestRate = Convert.ToDecimal(txtInterestRatePA.Text);

            SimpleInterestPaymentScheduleByTerm(term, loanAmount, daysBetweenRepayments, settlementDate, firstPaymentDate, annumInterestRate);
        }

        #region NoInterestPaymentSchedule

        protected void NoInterestPaymentSchedule(int term, decimal loanAmount, int daysBetweenRepayments,
                                                      DateTime settlementDate, DateTime firstPaymentDate)
        {
            DataTable dtSchedule = new DataTable();
            dtSchedule.Columns.Add("DueDate", typeof(DateTime));
            dtSchedule.Columns.Add("Repayment", typeof(decimal));
            dtSchedule.Columns.Add("Balance", typeof(decimal));

            settlementDate = firstPaymentDate.AddDays(-1 * daysBetweenRepayments);
            int daysFirstPeriod = (firstPaymentDate - settlementDate).Days;
            int totalDays = daysFirstPeriod + ((term - 1) * daysBetweenRepayments);
            decimal dailyDebitAmount = loanAmount / totalDays;

            decimal balance = loanAmount;

            for (int i = 0; i < term; i++)
            {
                DataRow dr = dtSchedule.NewRow();
                dr["DueDate"] = firstPaymentDate.AddDays(i * daysBetweenRepayments);
                decimal repaymentAmount;
                if (i == 0)
                {
                    repaymentAmount = dailyDebitAmount * daysFirstPeriod;
                }
                else
                {
                    repaymentAmount = dailyDebitAmount * daysBetweenRepayments;
                }

                dr["Repayment"] = repaymentAmount;
                if (balance - repaymentAmount > 0)
                {
                    balance = balance - repaymentAmount;
                }
                else
                {
                    dr["Repayment"] = balance;
                    balance = 0;
                }
                dr["Balance"] = balance;
                dtSchedule.Rows.Add(dr);
            }

            dvSchedule.DataSource = dtSchedule;
            dvSchedule.DataBind();
        }

        //protected DataTable NoInterestPaymentScheduleByTerm(int term, decimal loanAmount, int daysBetweenRepayments,
        //                                              DateTime settlementDate, DateTime firstPaymentDate)
        //{
        //    DataTable dtSchedule = new DataTable();
        //    dtSchedule.Columns.Add("DueDate", typeof(DateTime));
        //    dtSchedule.Columns.Add("Repayment", typeof(decimal));
        //    dtSchedule.Columns.Add("Balance", typeof(decimal));


        //    decimal balance = loanAmount;
        //    decimal termamount = loanAmount/term;
        //    decimal repaymentAmount = termamount;

        //    for (int i = 0; i < term; i++)
        //    {
        //        DataRow dr = dtSchedule.NewRow();
        //        dr["DueDate"] = firstPaymentDate.AddDays(i * daysBetweenRepayments);

        //        if (termamount>balance)
        //        {
        //            repaymentAmount = balance;
        //        }


        //        dr["Repayment"] = repaymentAmount;

        //            balance = balance - repaymentAmount;

        //        dr["Balance"] = balance;
        //        dtSchedule.Rows.Add(dr);
        //    }

        //    return dtSchedule;

        //}

        protected void NoInterestPaymentScheduleByRepayment(decimal repaymentAmount, decimal loanAmount,
                                                                     int daysBetweenRepayments, DateTime settlementDate,
                                                                     DateTime firstPaymentDate,
                                                                     decimal annumInterestRate)
        {
            DataTable dtSchedule = new DataTable();
            dtSchedule.Columns.Add("DueDate", typeof(DateTime));
            dtSchedule.Columns.Add("Repayment", typeof(decimal));
            dtSchedule.Columns.Add("Balance", typeof(decimal));

            int daysFirstPeriod = (firstPaymentDate - settlementDate).Days;
            decimal dailyInterestRate = annumInterestRate / 365;
            decimal dailyInterestAmount = loanAmount * dailyInterestRate;
            decimal balance = loanAmount;
            decimal firstrepayment = repaymentAmount;

            int i = 0;
            while (balance > 0)
            {
                DataRow dr = dtSchedule.NewRow();
                dr["DueDate"] = firstPaymentDate.AddDays(i * daysBetweenRepayments);

                if (i > 0)
                {
                    if (balance > firstrepayment)
                    {
                        repaymentAmount = firstrepayment;
                    }
                    else
                    {
                        repaymentAmount = balance;
                    }
                }
                dr["Repayment"] = repaymentAmount;
                balance = balance - repaymentAmount;
                dr["Balance"] = balance;
                dtSchedule.Rows.Add(dr);
                i++;
            }

            dvSchedule.DataSource = dtSchedule;
            dvSchedule.DataBind();
        }

        #endregion

        #region SimpleInterestPaymentSchedule

        protected void SimpleInterestPaymentScheduleByTerm(int term, decimal loanAmount, int daysBetweenRepayments,
                                                                DateTime settlementDate, DateTime firstPaymentDate,
                                                                decimal annumInterestRate)
        {
            DataTable dtSchedule = new DataTable();
            dtSchedule.Columns.Add("DueDate", typeof(DateTime));
            dtSchedule.Columns.Add("Repayment", typeof(decimal));
            dtSchedule.Columns.Add("Principal", typeof(decimal));
            dtSchedule.Columns.Add("Interest", typeof(decimal));
            dtSchedule.Columns.Add("Balance", typeof(decimal));

            var repaymentList = new List<RepaymentDetail>();

            int daysFirstPeriod = (firstPaymentDate - settlementDate).Days;
            decimal dailyInterestRate = annumInterestRate / 365;
            decimal dailyInterestAmount = loanAmount * dailyInterestRate;
            int totalDays = daysFirstPeriod + ((term - 1) * daysBetweenRepayments);
            decimal dailyPrincipal = loanAmount / totalDays;

            decimal balance = loanAmount;
            decimal totalInterestAmount = 0;
            for (int i = 0; i < term; i++)
            {
                DataRow dr = dtSchedule.NewRow();
                dr["DueDate"] = firstPaymentDate.AddDays(i * daysBetweenRepayments);
                decimal interestAmount;
                decimal principal;
                decimal repaymentAmount;
                if (i == 0)
                {
                    interestAmount = dailyInterestAmount * daysFirstPeriod;
                    repaymentAmount = (dailyInterestAmount + dailyPrincipal) * daysBetweenRepayments;
                    principal = repaymentAmount - interestAmount;
                }
                else
                {
                    interestAmount = dailyInterestAmount * daysBetweenRepayments;
                    principal = dailyPrincipal * daysBetweenRepayments;
                    repaymentAmount = principal + interestAmount;
                }
                dr["Interest"] = interestAmount;
                dr["Principal"] = principal;
                dr["Repayment"] = repaymentAmount;
                if (balance - principal > 0)
                {
                    balance = balance - principal;
                }
                else
                {
                    principal = balance;
                    dr["Principal"] = principal;
                    dr["Repayment"] = principal + interestAmount;
                    balance = 0;
                }
                dr["Balance"] = balance;
                totalInterestAmount += interestAmount;
                dtSchedule.Rows.Add(dr);

                repaymentList.Add(new RepaymentDetail { Date = Convert.ToDateTime(dr["DueDate"]), Amount = Convert.ToDecimal(dr["Repayment"]) });
            }

            DataRow drTotal = dtSchedule.NewRow();
            drTotal["interest"] = totalInterestAmount;
            dtSchedule.Rows.Add(drTotal);

            dvSchedule.DataSource = dtSchedule;
            dvSchedule.DataBind();

            repaymentList.Add(new RepaymentDetail { Date = Convert.ToDateTime(txtInsertRepaymentDate.Text), Amount = Convert.ToDecimal(txtInsertRepaymentAmount.Text) });
            dvChangedSchedule.DataSource = SimpleInterestGeneric(repaymentList, loanAmount, annumInterestRate, settlementDate);
            dvChangedSchedule.DataBind();
        }

        protected void SimpleInterestPaymentScheduleByRepayment(decimal repaymentAmount, decimal loanAmount,
                                                                     int daysBetweenRepayments, DateTime settlementDate,
                                                                     DateTime firstPaymentDate,
                                                                     decimal annumInterestRate)
        {
            DataTable dtSchedule = new DataTable();
            dtSchedule.Columns.Add("DueDate", typeof(DateTime));
            dtSchedule.Columns.Add("Repayment", typeof(decimal));
            dtSchedule.Columns.Add("Principal", typeof(decimal));
            dtSchedule.Columns.Add("Interest", typeof(decimal));
            dtSchedule.Columns.Add("Balance", typeof(decimal));

            var repaymentList = new List<RepaymentDetail>();

            int daysFirstPeriod = (firstPaymentDate - settlementDate).Days;
            decimal dailyInterestRate = annumInterestRate / 365;
            decimal dailyInterestAmount = loanAmount * dailyInterestRate;

            decimal balance = loanAmount;
            decimal totalInterestAmount = 0;
            int i = 0;
            while (balance > 0)
            {
                DataRow dr = dtSchedule.NewRow();
                dr["DueDate"] = firstPaymentDate.AddDays(i * daysBetweenRepayments);
                dr["Repayment"] = repaymentAmount;
                decimal interestAmount;
                if (i == 0)
                {
                    interestAmount = dailyInterestAmount * daysFirstPeriod;
                }
                else
                {
                    interestAmount = dailyInterestAmount * daysBetweenRepayments;
                }
                dr["Interest"] = interestAmount;
                decimal principal = repaymentAmount - interestAmount;
                dr["Principal"] = principal;
                if (balance - principal > 0)
                {
                    balance = balance - principal;
                }
                else
                {
                    principal = balance;
                    dr["Principal"] = principal;
                    dr["Repayment"] = principal + interestAmount;
                    balance = 0;
                }
                dr["Balance"] = balance;
                totalInterestAmount += interestAmount;
                dtSchedule.Rows.Add(dr);

                repaymentList.Add(new RepaymentDetail { Date = Convert.ToDateTime(dr["DueDate"]), Amount = Convert.ToDecimal(dr["Repayment"]) });

                i++;
            }

            DataRow drTotal = dtSchedule.NewRow();
            drTotal["interest"] = totalInterestAmount;
            dtSchedule.Rows.Add(drTotal);

            dvSchedule.DataSource = dtSchedule;
            dvSchedule.DataBind();

            repaymentList.Add(new RepaymentDetail { Date = Convert.ToDateTime(txtInsertRepaymentDate.Text), Amount = Convert.ToDecimal(txtInsertRepaymentAmount.Text) });
            dvChangedSchedule.DataSource = SimpleInterestGeneric(repaymentList, loanAmount, annumInterestRate, settlementDate);
            dvChangedSchedule.DataBind();
        }

        protected DataTable SimpleInterestGeneric(List<RepaymentDetail> repaymentList, decimal loanAmount, decimal annumInterestRate, DateTime settlementDate)
        {
            repaymentList.Sort((x, y) => x.Date.CompareTo(y.Date));

            DataTable dtSchedule = new DataTable();
            dtSchedule.Columns.Add("DueDate", typeof(DateTime));
            dtSchedule.Columns.Add("Repayment", typeof(decimal));
            dtSchedule.Columns.Add("Principal", typeof(decimal));
            dtSchedule.Columns.Add("Interest", typeof(decimal));
            dtSchedule.Columns.Add("Balance", typeof(decimal));

            decimal dailyInterestRate = annumInterestRate / 365;
            decimal dailyInterestAmount = loanAmount * dailyInterestRate;

            decimal balance = loanAmount;
            decimal cumulativeInterestAmount = 0;
            for (int i = 0; i < repaymentList.Count; i++)
            {
                DataRow dr = dtSchedule.NewRow();
                dr["DueDate"] = repaymentList[i].Date;
                dr["Repayment"] = repaymentList[i].Amount;
                decimal interestPaid;
                decimal principalPaid;
                if (i == 0)
                {
                    cumulativeInterestAmount = dailyInterestAmount * (repaymentList[i].Date - settlementDate).Days;
                }
                else
                {
                    cumulativeInterestAmount += dailyInterestAmount * (repaymentList[i].Date - repaymentList[i - 1].Date).Days;
                }

                if (repaymentList[i].Amount > cumulativeInterestAmount)
                {
                    interestPaid = cumulativeInterestAmount;
                    principalPaid = repaymentList[i].Amount - interestPaid;
                    cumulativeInterestAmount = 0;
                }
                else
                {
                    interestPaid = repaymentList[i].Amount;
                    principalPaid = 0;
                    cumulativeInterestAmount -= repaymentList[i].Amount;
                }
                dr["Interest"] = interestPaid;
                dr["Principal"] = principalPaid;

                balance = balance - principalPaid;
                dr["Balance"] = balance;
                dtSchedule.Rows.Add(dr);
            }

            return dtSchedule;
        }

        #endregion

        protected void btnSimpleGeneric_Click(object sender, EventArgs e)
        {
            var repaymentList = new List<RepaymentDetail>();
            repaymentList.Add(new RepaymentDetail { Date = new DateTime(2013, 3, 23), Amount = 30 });
            repaymentList.Add(new RepaymentDetail { Date = new DateTime(2013, 3, 28), Amount = 1000 });
            repaymentList.Add(new RepaymentDetail { Date = new DateTime(2013, 4, 2), Amount = 1000 });
            repaymentList.Add(new RepaymentDetail { Date = new DateTime(2013, 4, 9), Amount = 1000 });

            dvSchedule.DataSource = SimpleInterestGeneric(repaymentList, 11160, (decimal)0.5019, new DateTime(2013, 3, 20));
            dvSchedule.DataBind();
        }

    }

    public class RepaymentDetail
    {
        public DateTime Date { get; set; }
        public decimal Amount { get; set; }
        public decimal FeesCharged { get; set; }
        public decimal FeesPaid { get; set; }
    }

}